package com.jeesite.modules.digitalize.service;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.beust.jcommander.internal.Lists;
import com.bimface.api.bean.response.ModelCompareBean;
import com.jeesite.common.service.ServiceException;
import com.jeesite.modules.digitalize.constants.CompareStatusEnum;
import com.jeesite.modules.digitalize.dao.DigitalizeComponentCompareDao;
import com.jeesite.modules.digitalize.entity.DigitalizeComponentCompare;
import com.jeesite.modules.digitalize.entity.DigitalizeComponentIntegration;
import com.jeesite.modules.digitalize.entity.DigitalizeComponentVersion;
import com.jeesite.modules.digitalize.util.bimface.BimFaceUtils;
import com.jeesite.modules.digitalize.util.response.ResultVo;
import com.jeesite.modules.digitalize.util.word.compare.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * (DigitalizeComponentCompare)表服务实现类
 *
 * @author mxz
 * @since 2023-11-15 13:53:51
 */
@Service("digitalizeComponentCompareService")
public class DigitalizeComponentCompareService extends ServiceImpl<DigitalizeComponentCompareDao, DigitalizeComponentCompare> {

    @Resource
    BimFaceUtils bimFaceUtils;

    @Resource
    DigitalizeComponentVersionService digitalizeComponentVersionService;

    @Resource
    private DigitalizeComponentIntegrationService digitalizeComponentIntegrationService;

    public void export(HttpServletResponse response, Long id) {
        try {
            DigitalizeComponentCompare com = this.getById(id);
            if (CompareStatusEnum.IN_PROCESS.getCode().equals(com.getStatus())) {
                Integer comStatus = bimFaceUtils.getComStatus(com.getComparisonId());
                if (comStatus == 0) {
                    throw new ServiceException("对比结果正在处理中，不能导出");
                }
                if (comStatus == -1) {
                    com.setStatus(String.valueOf(comStatus));
                    this.updateById(com);
                    throw new ServiceException("对比结果失败，不能导出");
                }
                List<MyModelCompareDiff> comList = bimFaceUtils.getCompareData(com.getComparisonId());
                com.setData(comList != null ? JSON.toJSONString(comList): null);
                com.setStatus(CompareStatusEnum.SUCCESS.getCode());
                this.updateById(com);
            }
            if (!CompareStatusEnum.SUCCESS.getCode().equals(com.getStatus())) {
                throw new ServiceException("对比结果失败，不能导出");
            }
            if (StringUtils.isBlank(com.getData())) {
                throw new ServiceException("对比结果为空");
            }
            ChangeData changeData = constructDocdata(com.getData());
            WordExportUtils export = new WordExportUtils();
            //设置content—type
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset:utf-8");
            //设置标题
            String fileName = URLEncoder.encode("模型对比分析报告", "UTF-8");
            //Content-disposition是MIME协议的扩展，MIME协议指示MIME用户代理如何显示附加的文件。
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".docx");
            ServletOutputStream outputStream = response.getOutputStream();

            export.export(com, changeData,  outputStream);
            outputStream.close();
            //writer.close();
        } catch (IOException e) {
            throw new ServiceException("下载数据失败");
        }
    }


    public static ChangeData constructDocdata(String jsonData) {
        ChangeData changeData = new ChangeData();
        List<MyModelCompareDiff> data = JSON.parseArray(jsonData, MyModelCompareDiff.class);

        Map<String, List<MyModelCompareDiff>> diffMap = data.stream().collect(Collectors.groupingBy(MyModelCompareDiff::getDiffType));

        // 遍历获取各分类
        List<MyModelCompareDiff> myModelCompareDiffs = diffMap.get(DiffTypeEnum.CHANGE.getCode());
        if (CollectionUtil.isNotEmpty(myModelCompareDiffs)) {
            //遍历每个构件
            List<ComChange> list = new ArrayList<>();
            for (MyModelCompareDiff md : myModelCompareDiffs) {
                ComChange cc = new ComChange();
                cc.setCategoryName(md.getCategoryName());
                cc.setElementName(md.getFamily());
                cc.setElementId(md.getElementId());
                Map<String, List<ComChangeAttribute>> map = new HashMap<String, List<ComChangeAttribute>>();
                MyModelCompareChange diffData = md.getDiffData();

                List<Changed<Attribute>> changeAttributes = diffData.getChangeAttributes();
                AtomicInteger size = new AtomicInteger();
                changeAttributes.stream().forEach(item -> {
                    Attribute a = item.getA();
                    Attribute b = item.getB();
                    String key = a.getKey();
                    String[] a1 = key.split("-");
                    if (key.equals("_GeoFeature")) {
                        return;
                    }
                    ComChangeAttribute changed = new ComChangeAttribute();
                    changed.setKey(a1.length > 1 ? a1[1] : a1[0]).setValue(a.getValue()).setNewValue(b.getValue());
                    map.computeIfAbsent(a1[0], k -> Lists.newArrayList()).add(changed);
                    size.getAndIncrement();
                });

                List<Attribute> newAttributes = diffData.getNewAttributes();
                if (CollectionUtil.isNotEmpty(newAttributes)) {
                    newAttributes.stream().forEach(b -> {
                        String key = b.getKey();
                        String[] a1 = key.split("-");
                        if (key.equals("_GeoFeature")) {
                            return;
                        }
                        ComChangeAttribute changed = new ComChangeAttribute();
                        changed.setKey(a1.length > 1 ? a1[1] : a1[0]).setValue("").setNewValue(b.getValue());
                        map.computeIfAbsent(a1[0], k -> Lists.newArrayList()).add(changed);
                        size.getAndIncrement();
                    });
                }

                List<Attribute> deleteAttributes = diffData.getDeleteAttributes();
                if (CollectionUtil.isNotEmpty(deleteAttributes)) {
                    deleteAttributes.stream().forEach(b -> {
                        String key = b.getKey();
                        String[] a1 = key.split("-");
                        if (key.equals("_GeoFeature")) {
                            return;
                        }
                        ComChangeAttribute changed = new ComChangeAttribute();
                        changed.setKey(a1.length > 1 ? a1[1] : a1[0]).setValue(b.getValue()).setNewValue("");
                        map.computeIfAbsent(a1[0], k -> Lists.newArrayList()).add(changed);
                        size.getAndIncrement();
                    });
                }
                cc.setSize(size.get());
                cc.setChangedMap(map);
                list.add(cc);
            }
            changeData.setChangeDiffList(list);
        }
        changeData.setNewDiffList(diffMap.get(DiffTypeEnum.NEW.getCode()));
        changeData.setDeleteDiffList( diffMap.get(DiffTypeEnum.DELETE.getCode()));
        return changeData;
    }

    public ResultVo saveCompare(DigitalizeComponentCompare componentCompare) {
        ModelCompareBean compare = bimFaceUtils.compare(componentCompare);
        if (compare != null) {
            componentCompare.setComparisonId(compare.getCompareId());
            this.save(componentCompare);
            return ResultVo.success(componentCompare);
        } else {
            return ResultVo.failure("对比失败");
        }
    }

    public boolean callback(Long fileId, Long integrateId, Long compareId, String status) {
        if (null != compareId && 0 != compareId) {
            List<MyModelCompareDiff> comList = null;
            if (status.equals("success")) {
                comList = bimFaceUtils.getCompareData(compareId);
            }
            LambdaUpdateWrapper<DigitalizeComponentCompare> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(DigitalizeComponentCompare::getStatus, "success".equals(status) ? 1 : -1);
            updateWrapper.set(DigitalizeComponentCompare::getData, comList != null ? JSON.toJSONString(comList) : null);
            updateWrapper.eq(DigitalizeComponentCompare::getComparisonId, compareId);
            this.baseMapper.update(null, updateWrapper);
        } else if (null != fileId && 0 != fileId) {
            LambdaUpdateWrapper<DigitalizeComponentVersion> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(DigitalizeComponentVersion::getTransitionStatus, "success".equals(status) ? 2 : 3);
            updateWrapper.eq(DigitalizeComponentVersion::getFileId, fileId);
            digitalizeComponentVersionService.update(null, updateWrapper);
        } else if (null != integrateId && 0 != integrateId) {
            LambdaUpdateWrapper<DigitalizeComponentIntegration> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(DigitalizeComponentIntegration::getIntegrateldStatus, "success".equals(status) ? 1 : 2);
            updateWrapper.eq(DigitalizeComponentIntegration::getIntegrateld, integrateId);
            digitalizeComponentIntegrationService.update(null, updateWrapper);
        }
        return true;
    }
}

